﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Media;
using System.Threading;
using System.Threading.Tasks;

namespace WeatherRetriever
{
    public class WeatherSoundPlayer
    {
        private Weather currentlyPlayingWeather;
        private Thread soundPlayThread;
        private string folder;
        public event EventHandler<Weather> StartPlaying;
        public event EventHandler StoppedPlaying;

        private WeatherSoundPlayer(string soundFolder)
        {
            folder = soundFolder;
            currentlyPlayingWeather = null;
            soundPlayThread = null;
            StartPlaying += SetCurrentlyPlaying;
            StoppedPlaying += NullifyCurrentlyPlaying;
        }

        public void Play(Weather w)
        {
            if (Playing())
                throw new InvalidOperationException("Already playing");
            soundPlayThread = new Thread(new ThreadStart(PerformPlay));
            soundPlayThread.Start();
            StartPlaying.Invoke(this, w);
        }

        private List<string> ConvertNumberToWord(double number)
        {
            int num = (int)number;
            List<string> result = new List<string>();
            if (num > 499)
                throw new ArgumentOutOfRangeException("Maximum value is 499");
            switch (num / 100)
            {
                case 1:
                    result.Add("one hundred");
                    num -= 100;
                    break;
                case 2:
                    result.Add("two hundred");
                    num -= 200;
                    break;
                case 3:
                    result.Add("three hundred");
                    num -= 300;
                    break;
                case 4:
                    result.Add("four hundred");
                    num -= 400;
                    break;
            }

            switch (num / 10)
            {
                case 1:
                    switch (num % 10)
                    {
                        case 0:
                            result.Add("ten"); break;
                        case 1:
                            result.Add("eleven"); break;
                        case 2:
                            result.Add("twelve"); break;
                        case 3:
                            result.Add("thirteen"); break;
                        case 4:
                            result.Add("fourteen"); break;
                        case 5:
                            result.Add("fifteen"); break;
                        case 6:
                            result.Add("sixteen"); break;
                        case 7:
                            result.Add("seventeen"); break;
                        case 8:
                            result.Add("eighteen"); break;
                        case 9:
                            result.Add("nineteen"); break;
                    }
                    return result;
                case 2:
                    result.Add("twenty"); break;
                case 3:
                    result.Add("thirty"); break;
                case 4:
                    result.Add("forty"); break;
                case 5:
                    result.Add("fifty"); break;
                case 6:
                    result.Add("sixty"); break;
                case 7:
                    result.Add("seventy"); break;
                case 8:
                    result.Add("eighty"); break;
                case 9:
                    result.Add("ninety"); break;
            }

            switch (num % 10)
            {
                case 1:
                    result.Add("one"); break;
                case 2:
                    result.Add("two"); break;
                case 3:
                    result.Add("three"); break;
                case 4:
                    result.Add("four"); break;
                case 5:
                    result.Add("five"); break;
                case 6:
                    result.Add("six"); break;
                case 7:
                    result.Add("seven"); break;
                case 8:
                    result.Add("eight"); break;
                case 9:
                    result.Add("nine"); break;
            }

            if (result.Count == 0)
                result.Add("zero");

            return result;
        }
        // LEFTOFF - This function should synchronously do the real work of playing the sounds
        private void PerformPlay()
        {
            List<string> strs = ConvertNumberToWord(Math.Round(currentlyPlayingWeather.Temperature.Fahrenheit));
            SoundPlayer player = new SoundPlayer();
            foreach (string s in strs)
            {
                player.SoundLocation = folder + "\\numbers\\" + s + ".wav";
                player.PlaySync();
            }
        }

        private void NullifyCurrentlyPlaying(object sender, EventArgs e)
        {
 	        currentlyPlayingWeather = null;
            soundPlayThread = null;
        }

        private void SetCurrentlyPlaying(object sender, Weather w)
        {
 	        currentlyPlayingWeather = w;
        }

        public Weather CurrentlyPlayingWeather
        {
            get { return currentlyPlayingWeather; }
        }

        public string Folder
        {
            get { return folder; }
            set
            {
                if (ValidateDirectory(value))
                    folder = value;
                else
                    throw new ArgumentException("Specified directory does not exist or is invalid");
            }
        }

        public bool Playing()
        {
            return (currentlyPlayingWeather != null);
        }

        public static WeatherSoundPlayer CreateNew(string soundFolder)
        {
            if (ValidateDirectory(soundFolder))
                return new WeatherSoundPlayer(soundFolder);
            else
                throw new ArgumentException("Specified directory does not exist or is invalid");
        }

        public static bool ValidateDirectory(string directory)
        {
            if (Directory.Exists(directory))
            {
                bool numbers = false, conditions = false, misc = false;
                foreach (string str in Directory.EnumerateDirectories(directory))
                {
                    if (str.EndsWith("numbers"))
                        numbers = true;
                    else if (str.EndsWith("conditions"))
                        conditions = true;
                    else if (str.EndsWith("misc"))
                        misc = true;
                }

                if (numbers && conditions && misc)
                    return true;
            }
            return false;
        }

    }
}
